﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;

namespace Ewk.Extensions
{
    public static class UriExtensions
    {
        private const string KeyPairFormat = "{0}={1}";
        private const string AggregateFormat = "{0}&{1}";
        private const string UrlAndQueryStringFormat = "{0}?{1}";

        public static string ComposeQueryString(this IEnumerable<KeyValuePair<string, string>> queryParameters)
        {
            if (queryParameters == null) throw new ArgumentNullException("queryParameters");

            queryParameters = queryParameters.ToList();

            if (!queryParameters.Any()) return string.Empty;

            return queryParameters
                .Select(pair => string.Format(CultureInfo.InvariantCulture, KeyPairFormat, pair.Key, pair.Value))
                .Aggregate((pair1, pair2) => string.Format(CultureInfo.InvariantCulture, AggregateFormat, pair1, pair2));
        }

        public static Uri AddQueryStringParameters(this Uri uri, IEnumerable<KeyValuePair<string, string>> queryParameters)
        {
            var originalQueryParameters = uri.GetQueryParameters();

            foreach (var queryParameter in queryParameters)
            {
                if (originalQueryParameters.ContainsKey(queryParameter.Key)) continue;

                originalQueryParameters.Add(queryParameter);
            }

            if (originalQueryParameters.Count == 0)
            {
                return uri;
            }

            return new Uri(
                string.Format(CultureInfo.InvariantCulture,
                              UrlAndQueryStringFormat,
                              uri.GetLeftPart(UriPartial.Path),
                              originalQueryParameters.ComposeQueryString()));

        }

        public static Uri AddQueryStringParameters(this string url, IEnumerable<KeyValuePair<string, string>> queryParameters)
        {
            return new Uri(url).AddQueryStringParameters(queryParameters);
        }

        public static IDictionary<string, string> GetQueryParameters(this Uri uri)
        {
            var queryString = uri.Query;

            return string.IsNullOrEmpty(queryString)
                       ? new Dictionary<string, string>()
                       : queryString
                             .Trim('?')
                             .Split('&')
                             .Select(queryPair =>
                                     queryPair.Split('='))
                             .ToDictionary(keyValue => keyValue[0],
                                           keyValue => keyValue[1]);
        }
    }
}